package org.ruoyi.dhuman.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.core.utils.StringUtils;
import org.ruoyi.common.dhuman.config.properties.DhumanProperties;
import org.ruoyi.common.dhuman.utils.v1.TTS;
import org.ruoyi.common.dhuman.utils.v1.vo.DhumanExpressionVo;
import org.ruoyi.common.dhuman.utils.v1.vo.TTSExpressionVo;
import org.ruoyi.common.dhuman.utils.v1.vo.TTSVo;
import org.ruoyi.common.oss.entity.UploadResult;
import org.ruoyi.core.page.PageQuery;
import org.ruoyi.core.page.TableDataInfo;
import org.ruoyi.dhuman.domain.DhumanPpt;
import org.ruoyi.dhuman.domain.DhumanPptList;
import org.ruoyi.dhuman.domain.bo.DhumanPptBo;
import org.ruoyi.dhuman.domain.bo.DhumanPptListBo;
import org.ruoyi.dhuman.domain.vo.*;
import org.ruoyi.dhuman.enums.GenStatus;
import org.ruoyi.dhuman.mapper.DhumanPptListMapper;
import org.ruoyi.dhuman.mapper.DhumanPptMapper;
import org.ruoyi.dhuman.utils.CommonUtils;
import org.ruoyi.dhuman.vo.ReturnVo;
import org.ruoyi.dhuman.vo.UploadResult2;
import org.ruoyi.ppt.domain.PptImage;
import org.ruoyi.ppt.domain.PptWithImages;
import org.ruoyi.ppt.service.PptService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;

@RequiredArgsConstructor
@Slf4j
@Service
public class DhumanJobService {
	private final DhumanProperties dhumanProperties;
	private final IDhumanPptService dhumanPptService;
	private final IDhumanPptListService dhumanPptListService;
	private final PptService pptService;
	private final GenService genService;
	private final DhumanPptMapper dhumanPptMapper;
	private final DhumanPptListMapper baseMapper;

	private List<DhumanPptListVo> queryDhumanPptIdOrderByImapgeSortAsc(long pptId) {
		LambdaQueryWrapper<DhumanPptList> lqw = Wrappers.lambdaQuery();
		lqw.eq(DhumanPptList::getDhumanPptId, pptId);
		lqw.orderByAsc(DhumanPptList::getImageSort);

		return baseMapper.selectVoList(lqw);
	}

	public TableDataInfo<DhumanPptJobVo> selectAllocatedList(DhumanPptBo humanPpt, PageQuery pageQuery) {
		QueryWrapper<DhumanPpt> wrapper = Wrappers.query();
//		wrapper.eq("u.del_flag", UserConstants.USER_NORMAL)
//			.eq(ObjectUtil.isNotNull(user.getRoleId()), "r.role_id", user.getRoleId())
//			.like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName())
//			.eq(StringUtils.isNotBlank(user.getStatus()), "u.status", user.getStatus())
//			.like(StringUtils.isNotBlank(user.getPhonenumber()), "u.phonenumber", user.getPhonenumber());
		Page<DhumanPptJobVo> page = dhumanPptMapper.selectJobList(pageQuery.build(), wrapper);
		return TableDataInfo.build(page);
	}

	public R<DhumanPptVo> uploadAndSavePPT(MultipartFile file) {
		List<UploadResult2> uploadResults;
		try {
			String ocrLanguagePath = dhumanProperties.getOcrLanguagePath();
			uploadResults = CommonUtils.uploadPPT(dhumanProperties.getWorkpath(), file, ocrLanguagePath);
		} catch (Exception e) {
			log.error(e.getMessage());
			return R.fail(e.getMessage());
		}

		DhumanPptBo dhumanPptBo = new DhumanPptBo();
		dhumanPptBo.setPptName(file.getOriginalFilename());
		dhumanPptBo.setStatus(GenStatus.WAITING.toString());
		dhumanPptBo.setCreateTime(new Date());
		dhumanPptBo.setUpdateTime(new Date());
		dhumanPptService.insertByBo(dhumanPptBo);

		List<DhumanPptListVo> list = new ArrayList<>();
		for (int i = 0; i < uploadResults.size(); i++) {
			UploadResult2 uploadResult = uploadResults.get(i);
			String copyText = uploadResult.getTextContent();
			if (StringUtils.isNotEmpty(copyText) && copyText.length() > DhumanProperties.ttsMaxCharacters) {
				copyText = copyText.substring(0, DhumanProperties.ttsMaxCharacters);
			}
			// 保存文件信息
			DhumanPptListBo dhumanPptListBo = new DhumanPptListBo();
			dhumanPptListBo.setDhumanPptId(dhumanPptBo.getId());
			dhumanPptListBo.setImageUrl(uploadResult.getUrl());
			dhumanPptListBo.setImageName(uploadResult.getFilename());
			dhumanPptListBo.setCopyText(copyText);
			dhumanPptListBo.setImageSort((long) i);
			dhumanPptListBo.setTtsStatus(GenStatus.WAITING.toString());
			dhumanPptListBo.setDhumanStatus(GenStatus.WAITING.toString());
			dhumanPptListBo.setCreateTime(new Date());
			dhumanPptListBo.setUpdateTime(new Date());
			dhumanPptListService.insertByBo(dhumanPptListBo);
			DhumanPptListVo dhumanPptListVo = new DhumanPptListVo();
			BeanUtils.copyProperties(dhumanPptListBo, dhumanPptListVo);
//			DhumanPptListVo dhumanPptListVo = MapstructUtils.convert(dhumanPptListBo, DhumanPptListVo.class);
			list.add(dhumanPptListVo);
		}

		DhumanPptVo dhumanPptVo = new DhumanPptVo();
		BeanUtils.copyProperties(dhumanPptBo, dhumanPptVo);
//		DhumanPptVo dhumanPptVo = MapstructUtils.convert(dhumanPptBo, DhumanPptVo.class);
		if (dhumanPptVo != null) {
			dhumanPptVo.setList(list);
		}
		return R.ok(dhumanPptVo);
	}

	public R<DhumanPptVo> selectPPTFromPPTModule(String id) {
		PptWithImages pptWithImages = pptService.getPptImages(id);

		DhumanPptBo dhumanPptBo = new DhumanPptBo();
		dhumanPptBo.setPptName(pptWithImages.getPptTitle());
		dhumanPptBo.setStatus(GenStatus.WAITING.toString());
		dhumanPptBo.setCreateTime(new Date());
		dhumanPptBo.setUpdateTime(new Date());
		dhumanPptService.insertByBo(dhumanPptBo);

		List<PptImage> images = pptWithImages.getImages();
		List<DhumanPptListVo> list = new ArrayList<>();
		for (int i = 0; i < images.size(); i++) {
			PptImage pptImage = images.get(i);
			// 保存文件信息
			DhumanPptListBo dhumanPptListBo = new DhumanPptListBo();
			dhumanPptListBo.setDhumanPptId(dhumanPptBo.getId());
			dhumanPptListBo.setImageUrl(pptImage.getImageUrl());
//			dhumanPptListBo.setImageName(pptImage.get);
			dhumanPptListBo.setImageSort((long) i);
			dhumanPptListBo.setTtsStatus(GenStatus.WAITING.toString());
			dhumanPptListBo.setDhumanStatus(GenStatus.WAITING.toString());
			dhumanPptListBo.setCreateTime(new Date());
			dhumanPptListBo.setUpdateTime(new Date());
			dhumanPptListService.insertByBo(dhumanPptListBo);
			DhumanPptListVo dhumanPptListVo = new DhumanPptListVo();
			BeanUtils.copyProperties(dhumanPptListBo, dhumanPptListVo);
//			DhumanPptListVo dhumanPptListVo = MapstructUtils.convert(dhumanPptListBo, DhumanPptListVo.class);
			list.add(dhumanPptListVo);
		}

		DhumanPptVo dhumanPptVo = new DhumanPptVo();
		BeanUtils.copyProperties(dhumanPptBo, dhumanPptVo);
//		DhumanPptVo dhumanPptVo = MapstructUtils.convert(dhumanPptBo, DhumanPptVo.class);
		if (dhumanPptVo != null) {
			dhumanPptVo.setList(list);
		}
		return R.ok(dhumanPptVo);
	}


	public R<DhumanPptVo> loadPPTJob(long id) {
		DhumanPptVo dhumanPptVo = dhumanPptService.queryById(id);

		List<DhumanPptListVo> list = queryDhumanPptIdOrderByImapgeSortAsc(dhumanPptVo.getId());
		dhumanPptVo.setList(list);

		return R.ok(dhumanPptVo);
	}

	public R<DhumanPptVo> copyPPTJob(long id) {
		DhumanPptVo dhumanPptVo = dhumanPptService.queryById(id);

		List<DhumanPptListVo> dbList = queryDhumanPptIdOrderByImapgeSortAsc(dhumanPptVo.getId());

		DhumanPptBo newDhumanPptBo = new DhumanPptBo();
		BeanUtils.copyProperties(dhumanPptVo, newDhumanPptBo);
		newDhumanPptBo.setId(null);
		newDhumanPptBo.setPptName(dhumanPptVo.getPptName() + " - 副本");
		newDhumanPptBo.setStatus(GenStatus.WAITING.toString());
		newDhumanPptBo.setCreateTime(new Date());
		newDhumanPptBo.setUpdateTime(new Date());
		dhumanPptService.insertByBo(newDhumanPptBo);

		List<DhumanPptListVo> list = new ArrayList<>();
		for (int i = 0; i < dbList.size(); i++) {
			DhumanPptListVo dhumanPptListVo = dbList.get(i);
			DhumanPptListBo dhumanPptListBo = new DhumanPptListBo();
			BeanUtils.copyProperties(dhumanPptListVo, dhumanPptListBo);

			dhumanPptListBo.setId(null);
			dhumanPptListBo.setDhumanPptId(newDhumanPptBo.getId());
			dhumanPptListBo.setImageSort((long) i);
			dhumanPptListBo.setTtsStatus(GenStatus.WAITING.toString());
			dhumanPptListBo.setDhumanStatus(GenStatus.WAITING.toString());
			dhumanPptListBo.setCreateTime(new Date());
			dhumanPptListBo.setUpdateTime(new Date());
			dhumanPptListService.insertByBo(dhumanPptListBo);

			dhumanPptListVo = new DhumanPptListVo();
			BeanUtils.copyProperties(dhumanPptListBo, dhumanPptListVo);
			list.add(dhumanPptListVo);
		}

		dhumanPptVo.setList(list);

		return R.ok(dhumanPptVo);
	}

	public R genTTS(TTSRequestVo vo) {
		String copyText = vo.getCopyText();
		if (StringUtils.isEmpty(copyText)) {
			return R.fail("copyText 不能为空");
		}
		ObjectMapper objectMapper = new ObjectMapper();
		TTSExpressionVo expressionVo = new TTSExpressionVo();
		try {
			expressionVo = objectMapper.readValue(vo.getTtsExpression(), TTSExpressionVo.class);
		} catch (Exception e) {
			return R.fail(e.getMessage());
		}

		long id = Long.parseLong(vo.getId());
		DhumanPptListBo bo = new DhumanPptListBo();
		bo.setId(id);
		bo.setCopyText(vo.getCopyText());
		bo.setTtsExpression(vo.getTtsExpression());
		bo.setTtsStatus(GenStatus.GENERATING.toString());
		boolean flag = dhumanPptListService.updateByBo(bo);
		if (!flag) {
			return R.fail("操作失败");
		}

		TTS tts = new TTS(dhumanProperties.getTtsAppid(), dhumanProperties.getTtsAppsecret(), dhumanProperties.getTtsEndpoint());
		TTSVo requestVO = new TTSVo();
		BeanUtils.copyProperties(expressionVo, requestVO);
		requestVO.setText(vo.getCopyText());
		String response = tts.doTTS(requestVO);
		log.info("TTS Response: " + response);

		ObjectMapper mapper = new ObjectMapper();
		JsonNode jsonNode = null;
		try {
			jsonNode = mapper.readTree(response);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}

		bo.setTtsResponse(response);
		if (jsonNode.has("code") && null != jsonNode.get("code") && "0".equals(jsonNode.get("code").asText())) {
			String audioUrl = jsonNode.get("data").get("tts").get("url").asText();
			bo.setTtsAudioUrl(audioUrl);
			bo.setTtsStatus(GenStatus.DONE.toString());
		} else {
			bo.setTtsStatus(GenStatus.FAILED.toString());
		}

		flag = dhumanPptListService.updateByBo(bo);

		return flag? R.ok(bo) : R.fail("服务器繁忙，请稍后重试");
	}

	public R preview(Long pptId) {
		try {
			DhumanPptVo dhumanPptVo = genService.genVideoNoDhuman(pptId);
			if (dhumanPptVo == null) {
				return R.fail("服务器繁忙，请稍后重试");
			}
			return R.ok(dhumanPptVo);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return R.fail("服务器繁忙，请稍后重试", new ReturnVo(e.getMessage()));
		}
	}

	public R genVideo(Long pptId) {
		try {
			DhumanPptVo dhumanPptVo = genService.genVideoWithDhuman(pptId);
			if (dhumanPptVo == null) {
				return R.fail("服务器繁忙，请稍后重试");
			}
			return R.ok(dhumanPptVo);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return R.fail("服务器繁忙，请稍后重试", new ReturnVo(e.getMessage()));
		}
	}

	public R<DhumanPptVo> saveListWithV1(Long pptId, List<SubVideoRequestVo> voList) {
		DhumanPptVo dhumanPptVo = dhumanPptService.queryById(pptId);
		if (!GenStatus.WAITING.toString().equals(dhumanPptVo.getStatus())) {
			return R.fail("当前状态不允许编辑");
		}

		List<DhumanPptListVo> list = queryDhumanPptIdOrderByImapgeSortAsc(dhumanPptVo.getId());
		Map<Long, DhumanPptListVo> map = new HashMap<>();
		if (list != null && list.size() > 0) {
			for (DhumanPptListVo vo : list) {
				map.put(vo.getId(), vo);
			}
		}

		for (int i = 0; i < voList.size(); i++) {
			SubVideoRequestVo vo = voList.get(i);
			if (StringUtils.isNotEmpty(vo.getId())) {
				DhumanPptListVo dhumanPptListVo = map.get(Long.parseLong(vo.getId()));;
				if (dhumanPptListVo == null) {
					return R.fail("第【" + i + "】数据不存在,请检查");
				}
				if (!GenStatus.WAITING.toString().equals(dhumanPptListVo.getDhumanStatus())) {
					return R.fail("第【" + i + "】数据当前前状态不允许编辑");
				}
			}

			String ttsExpression = vo.getTtsExpression();
			ObjectMapper objectMapper = new ObjectMapper();
			try {
				if (StringUtils.isNotEmpty(ttsExpression)) {
					objectMapper.readValue(ttsExpression, TTSExpressionVo.class);
				}
			} catch (Exception e) {
				return R.fail(e.getMessage());
			}

			String dhumanExpression = vo.getDhumanExpression();
			try {
				if (StringUtils.isNotEmpty(dhumanExpression)) {
					objectMapper.readValue(dhumanExpression, DhumanExpressionVo.class);
				}
			} catch (Exception e) {
				return R.fail(e.getMessage());
			}
		}

		for (int i = 0; i < voList.size(); i++) {
			SubVideoRequestVo vo = voList.get(i);

			if (StringUtils.isNotEmpty(vo.getId())) {
				// 修改
				long id = Long.parseLong(vo.getId());
				DhumanPptListVo dhumanPptListVo = map.get(id);;
				DhumanPptListBo bo = new DhumanPptListBo();
				bo.setId(id);
				bo.setCopyText(vo.getCopyText());
				bo.setTtsExpression(vo.getTtsExpression());
				bo.setDhumanExpression(vo.getDhumanExpression());
				bo.setImageSort((long) i);
				bo.setUpdateTime(new Date());

				String dbCopyText = dhumanPptListVo.getCopyText();
				String copyText = vo.getCopyText();
				if ((dbCopyText != null && !dbCopyText.equals(copyText)) || dbCopyText == null) {
					// 两者不相同时须新合成音频
					bo.setTtsStatus(GenStatus.WAITING.toString());
					bo.setTtsAudioUrl(null);
					bo.setTtsSrtUrl(null);
				}

				boolean flag = dhumanPptListService.updateByBo(bo);

				if (!flag) {
					return R.fail("服务器繁忙，请稍后重试");
				}
			} else {
				String dhumanExpression = vo.getDhumanExpression();
				DhumanExpressionVo dhumanExpressionVo = new DhumanExpressionVo();
				try {
					if (StringUtils.isNotEmpty(dhumanExpression)) {
						dhumanExpressionVo = new ObjectMapper().readValue(dhumanExpression, DhumanExpressionVo.class);
					}
				} catch (Exception e) {
					return R.fail(e.getMessage());
				}

				// 新增
				DhumanPptListBo dhumanPptListBo = new DhumanPptListBo();
				dhumanPptListBo.setDhumanPptId(pptId);
				dhumanPptListBo.setImageUrl(dhumanExpressionVo.getPptUrl());
				dhumanPptListBo.setImageSort((long) i);
				dhumanPptListBo.setTtsStatus(GenStatus.WAITING.toString());
				dhumanPptListBo.setDhumanStatus(GenStatus.WAITING.toString());
				dhumanPptListBo.setCreateTime(new Date());
				dhumanPptListBo.setUpdateTime(new Date());
				dhumanPptListService.insertByBo(dhumanPptListBo);
			}
		}

		return loadPPTJob(pptId);
	}

	public R<DhumanPptVo> reSortListWithV1(Long pptId, List<SubVideoRequestVo> voList) {
		DhumanPptVo dhumanPptVo = dhumanPptService.queryById(pptId);
		if (!GenStatus.WAITING.toString().equals(dhumanPptVo.getStatus())) {
			return R.fail("当前状态不允许编辑");
		}

		DhumanPptListBo dhumanPptListBo = new DhumanPptListBo();
		dhumanPptListBo.setDhumanPptId(pptId);
		List<DhumanPptListVo> list = queryDhumanPptIdOrderByImapgeSortAsc(pptId);
		Map<Long, DhumanPptListVo> map = new HashMap<>();
		if (list != null && list.size() > 0) {
			for (DhumanPptListVo vo : list) {
				map.put(vo.getId(), vo);
			}
		}

		for (int i = 0; i < voList.size(); i++) {
			SubVideoRequestVo vo = voList.get(i);
			if (StringUtils.isNotEmpty(vo.getId())) {
				DhumanPptListVo dhumanPptListVo = map.get(vo.getId());;
				if (dhumanPptListVo == null) {
					return R.fail("第【" + i + "】数据不存在,请检查");
				}
				if (!GenStatus.WAITING.toString().equals(dhumanPptListVo.getDhumanStatus())) {
					return R.fail("第【" + i + "】数据当前前状态不允许编辑");
				}
			}
		}

		for (int i = 0; i < voList.size(); i++) {
			SubVideoRequestVo vo = voList.get(i);
			long id = Long.parseLong(vo.getId());

			DhumanPptListBo bo = new DhumanPptListBo();
			bo.setId(id);
			bo.setImageSort((long) i);
			bo.setUpdateTime(new Date());

			dhumanPptListService.updateByBo(bo);
		}

		return loadPPTJob(pptId);
	}

	public R<DhumanPptVo> saveSubVideoExpressionVoWithV1(SubVideoRequestVo vo) {
		String ttsExpression = vo.getTtsExpression();
		ObjectMapper objectMapper = new ObjectMapper();
		try {
			objectMapper.readValue(ttsExpression, TTSExpressionVo.class);
		} catch (Exception e) {
			return R.fail(e.getMessage());
		}
		if (StringUtils.isEmpty(vo.getId())) {
			return R.fail("id 不能为空");
		}

		String dhumanExpression = vo.getDhumanExpression();
		try {
			objectMapper.readValue(dhumanExpression, DhumanExpressionVo.class);
		} catch (Exception e) {
			return R.fail(e.getMessage());
		}

		Long id = Long.parseLong(vo.getId());
		DhumanPptListVo dhumanPptListVo = dhumanPptListService.queryById(id);
		if (dhumanPptListVo == null) {
			return R.fail("数据不存在");
		}
		DhumanPptVo dhumanPptVo = dhumanPptService.queryById(dhumanPptListVo.getDhumanPptId());
		if (!GenStatus.WAITING.toString().equals(dhumanPptVo.getStatus())) {
			return R.fail("当前状态不允许编辑");
		}

		if (!GenStatus.WAITING.toString().equals(dhumanPptListVo.getDhumanStatus())) {
			return R.fail("当前状态不允许编辑");
		}

		DhumanPptListBo bo = new DhumanPptListBo();
		bo.setId(id);
		bo.setCopyText(vo.getCopyText());
		bo.setTtsExpression(vo.getTtsExpression());
		bo.setDhumanExpression(vo.getDhumanExpression());
		bo.setUpdateTime(new Date());

		String dbCopyText = dhumanPptListVo.getCopyText();
		String copyText = vo.getCopyText();
		if ((dbCopyText != null && !dbCopyText.equals(copyText)) || dbCopyText == null) {
			// 两者不相同时须新合成音频
			bo.setTtsStatus(GenStatus.WAITING.toString());
			bo.setTtsAudioUrl(null);
			bo.setTtsSrtUrl(null);
		}

		boolean flag = dhumanPptListService.updateByBo(bo);

		if (flag) {
			return loadPPTJob(dhumanPptListVo.getDhumanPptId());
		} else {
			return R.fail("服务器繁忙，请稍后重试");
		}
	}
}
